﻿#pragma once
#include <string>
#include <map>
#include <vector>
//#include "EightChar.h"
//#include "Solar.h"

class EightChar;
class Foto;
class Tao;
class LunarYear;
class Solar;

/// <summary>
/// 农历日期
/// </summary>
class Lunar
{
public:
    /// <summary>
    /// 节气表，国标以冬至为首个节气
    /// </summary>
    static const std::vector<std::string>  JIE_QI;
    
    /// <summary>
    /// 实际的节气表
    /// </summary>
    static const std::vector<std::string> JIE_QI_IN_USE;
    
    /// <summary>
    /// 农历年
    /// </summary>
    int Year;
    
    /// <summary>
    /// 农历月，闰月为负，即闰2月=-2
    /// </summary>
    int Month;
    
    /// <summary>
    /// 农历日
    /// </summary>
    int Day;
    
    /// <summary>
    /// 对应阳历
    /// </summary>
    Solar* solar;
    
    /// <summary>
    /// 时对应的天干下标，0-9
    /// </summary>
    int TimeGanIndex;
    
    /// <summary>
    /// 时对应的地支下标，0-11
    /// </summary>
    int TimeZhiIndex;
    
    /// <summary>
    /// 日对应的天干下标，0-9
    /// </summary>
    int DayGanIndex;
    
    /// <summary>
    /// 日对应的地支下标，0-11
    /// </summary>
    int DayZhiIndex;
    
    /// <summary>
    /// 日对应的天干下标（八字流派1，晚子时日柱算明天），0-9
    /// </summary>
    int DayGanIndexExact;
    
    /// <summary>
    /// 日对应的地支下标（八字流派1，晚子时日柱算明天），0-11
    /// </summary>
    int DayZhiIndexExact;
    
    /// <summary>
    /// 日对应的天干下标（八字流派2，晚子时日柱算当天），0-9
    /// </summary>
    int DayGanIndexExact2;
    
    /// <summary>
    /// 日对应的地支下标（八字流派2，晚子时日柱算当天），0-11
    /// </summary>
    int DayZhiIndexExact2;
    
    /// <summary>
    /// 月对应的天干下标（以节交接当天起算），0-9
    /// </summary>
    int MonthGanIndex;
    
    /// <summary>
    /// 月对应的地支下标（以节交接当天起算），0-11
    /// </summary>
    int MonthZhiIndex;
    
    /// <summary>
    /// 月对应的天干下标（八字流派1，晚子时日柱算明天），0-9
    /// </summary>
    int MonthGanIndexExact;
    
    /// <summary>
    /// 月对应的地支下标（八字流派1，晚子时日柱算明天），0-11
    /// </summary>
    int MonthZhiIndexExact;
    
    /// <summary>
    /// 年对应的天干下标（国标，以正月初一为起点），0-9
    /// </summary>
    int YearGanIndex;
    
    /// <summary>
    /// 年对应的地支下标（国标，以正月初一为起点），0-11
    /// </summary>
    int YearZhiIndex;
    
    /// <summary>
    /// 年对应的天干下标（月干计算用，以立春为起点），0-9
    /// </summary>
    int YearGanIndexByLiChun;
    
    /// <summary>
    /// 年对应的地支下标（月支计算用，以立春为起点），0-11
    /// </summary>
    int YearZhiIndexByLiChun;
    
    /// <summary>
    /// 年对应的天干下标（最精确的，供八字用，以立春交接时刻为起点），0-9
    /// </summary>
    int YearGanIndexExact;
    
    /// <summary>
    /// 年对应的地支下标（最精确的，供八字用，以立春交接时刻为起点），0-11
    /// </summary>
    int YearZhiIndexExact;
    
    /// <summary>
    /// 周下标，0-6
    /// </summary>
    int WeekIndex;
    
    /// <summary>
    /// 阳历小时
    /// </summary>
    int Hour;
    
    /// <summary>
    /// 阳历分钟
    /// </summary>
    int Minute;
    
    /// <summary>
    /// 阳历秒钟
    /// </summary>
    int Second;
    
    /// <summary>
    /// 节气表
    /// </summary>
    std::map<std::string, Solar> JieQiTable;
    
    /// <summary>
    /// 八字
    /// </summary>
    EightChar* getEightChar();
    
    /// <summary>
    /// 佛历
    /// </summary>
    Foto* getFoto();
    
    
    /// <summary>
    /// 道历
    /// </summary>
    Tao* getTao();
    
    
    /// <summary>
    /// 默认使用当前日期初始化
    /// </summary>
    Lunar();
    
    /// <summary>
    /// 通过农历年月日时分秒初始化
    /// </summary>
    /// <param name="lunarYear">年（农历）</param>
    /// <param name="lunarMonth">月（农历），1到12，闰月为负，即闰2月=-2</param>
    /// <param name="lunarDay">日（农历），1到31</param>
    /// <param name="hour">小时（阳历）</param>
    /// <param name="minute">分钟（阳历）</param>
    /// <param name="second">秒钟（阳历）</param>
    Lunar(int lunarYear, int lunarMonth, int lunarDay, int hour = 0, int minute = 0, int second = 0);
    
    /// <summary>
    /// 通过指定农历年月日时分秒获取农历
    /// </summary>
    /// <param name="lunarYear">年（农历）</param>
    /// <param name="lunarMonth">月（农历），1到12，闰月为负，即闰2月=-2</param>
    /// <param name="lunarDay">日（农历），1到31</param>
    /// <param name="hour">小时（阳历）</param>
    /// <param name="minute">分钟（阳历）</param>
    /// <param name="second">秒钟（阳历）</param>
    /// <returns>农历</returns>
    static Lunar* FromYmdHms(int lunarYear, int lunarMonth, int lunarDay, int hour = 0, int minute = 0, int second = 0);
    
    
    /// <summary>
    /// 通过阳历初始化
    /// </summary>
    /// <param name="solar">阳历</param>
    Lunar(Solar* solar);
    
    /// <summary>
    /// 干支纪日（日柱，八字流派2，晚子时日柱算当天），如己卯
    /// </summary>
    std::string DayInGanZhiExact2();
    
    /// <summary>
    /// 日天干（八字流派2，晚子时日柱算当天），如甲
    /// </summary>
    std::string DayGanExact2();
    
    
    /// <summary>
    /// 日地支（八字流派2，晚子时日柱算当天），如卯
    /// </summary>
    /// <returns>日地支</returns>
    std::string DayZhiExact2();
    
    /// <summary>
    /// 干支纪日（日柱，八字流派1，晚子时日柱算明天），如己卯
    /// </summary>
    std::string DayInGanZhiExact();
    
    
    /// <summary>
    /// 日天干（八字流派1，晚子时日柱算明天），如甲
    /// </summary>
    std::string DayGanExact();
    
    
    /// <summary>
    /// 日地支（八字流派1，晚子时日柱算明天），如卯
    /// </summary>
    std::string DayZhiExact();
    
    /// <summary>
    /// 干支纪年（年柱）（以立春交接的时刻作为新年的开始），如辛亥
    /// </summary>
    std::string YearInGanZhiExact();
    
    /// <summary>
    /// 最精确的年天干（以立春交接的时刻作为新年的开始），如辛
    /// </summary>
    std::string YearGanExact();
    
    /// <summary>
    /// 最精确的年地支（以立春交接的时刻作为新年的开始），如亥
    /// </summary>
    std::string YearZhiExact();
    
    /// <summary>
    /// 精确的干支纪月（月柱）（以节交接时刻起算），如己卯，月天干口诀：甲己丙寅首，乙庚戊寅头。丙辛从庚寅，丁壬壬寅求，戊癸甲寅居，周而复始流。月地支：正月起寅。
    /// </summary>
    std::string MonthInGanZhiExact();
    
    /// <summary>
    /// 精确的月天干（以节交接时刻起算），如己
    /// </summary>
    std::string MonthGanExact();
    
    /// <summary>
    /// 精确的月地支（以节交接时刻起算），如卯
    /// </summary>
    std::string MonthZhiExact();
    
    /// <summary>
    /// 时辰干支（时柱）
    /// </summary>
    std::string TimeInGanZhi();
    
    /// <summary>
    /// 时辰天干
    /// </summary>
    std::string TimeGan();
    
    /// <summary>
    /// 时辰地支
    /// </summary>
    std::string TimeZhi();
    
    /// <summary>
    /// 日宜，如果没有，返回["无"]，默认流派1
    /// </summary>
    std::vector<std::string> DayYi();
    
    /// <summary>
    /// 日宜，如果没有，返回["无"]
    /// </summary>
    /// <param name="sect">流派，1以节交接当天起算月，2以节交接时刻起算月</param>
    /// <returns>宜</returns>
    std::vector<std::string> GetDayYi(int sect = 1);
    
    
    /// <summary>
    /// 干支纪月（月柱）（以节交接当天起算），如己卯，月天干口诀：甲己丙寅首，乙庚戊寅头。丙辛从庚寅，丁壬壬寅求，戊癸甲寅居，周而复始流。月地支：正月起寅。
    /// </summary>
    std::string MonthInGanZhi();
    
    /// <summary>
    /// 干支纪日（日柱），如己卯
    /// </summary>
    std::string DayInGanZhi();
    /// <summary>
    /// 月天干，如己
    /// </summary>
    std::string MonthGan();
    
    /// <summary>
    /// 月地支，如卯
    /// </summary>
    std::string MonthZhi();
    
    /// <summary>
    /// 日天干，如甲
    /// </summary>
    std::string DayGan();
    
    /// <summary>
    /// 日地支，如卯
    /// </summary>
    std::string DayZhi();
    
    ~Lunar();
    
    /// <summary>
    /// 日忌，如果没有，返回["无"]
    /// </summary>
    /// <param name="sect">流派，1以节交接当天起算月，2以节交接时刻起算月</param>
    /// <returns>忌</returns>
    std::vector<std::string> GetDayJi(int sect = 1);
    
    /// <summary>
    /// 日吉神（宜趋），如果没有，返回["无"]
    /// </summary>
    std::vector<std::string> DayJiShen();
    
    
    /// <summary>
    /// 日凶煞（宜忌），如果没有，返回["无"]
    /// </summary>
    std::vector<std::string> DayXiongSha();
    
    
    /// <summary>
    /// 彭祖百忌天干
    /// </summary>
    std::string PengZuGan();
    
    /// <summary>
    /// 彭祖百忌地支
    /// </summary>
    std::string PengZuZhi();
    
    /// <summary>
    /// 干支纪年（年柱）（以正月初一作为新年的开始），如辛亥
    /// </summary>
    std::string YearInGanZhi();
    
    /// <summary>
    /// 年天干（以正月初一作为新年的开始），如辛
    /// </summary>
    std::string YearGan();
    
    /// <summary>
    /// 年地支（以正月初一作为新年的开始），如亥
    /// </summary>
    std::string YearZhi();

    /// <summary>
    /// 中文月，如正
    /// </summary>
    std::string MonthInChinese();

    /// <summary>
    /// 中文日，如初一
    /// </summary>
    std::string DayInChinese();
    
private:
    EightChar* _eightChar;
    
    Foto* _foto;
    
    Tao* _tao;
    
    void Compute(LunarYear& lunarYear);
    
    /// <summary>
    /// 计算节气表
    /// </summary>
    void ComputeJieQi(LunarYear& lunarYear);
    /// <summary>
    /// 计算干支纪年
    /// </summary>
    void ComputeYear();;
    
    /**
    * 干支纪月计算
    */
    void ComputeMonth();
    
    /// <summary>
    /// 干支纪日计算
    /// </summary>
    void ComputeDay();
    
    
    /// <summary>
    /// 干支纪时计算
    /// </summary>
    void ComputeTime();
    
    void ComputeWeek();
};



